﻿using ManageSystem.IService;
using ManageSystem.Model;
using ManageSystem.Repository;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace ManageSystem.Service
{
    public class ProjectService : BaseService<Project>, IProjectService
    {
        // this class have a baseRepository(inherited from BaseService) and it's projectRepository
        public ProjectRepository projectDal = new();

        // this service notice the projectRepository 

        /// <summary>
        /// 根据username查询项目(多对多查询)
        /// </summary>
        /// <param name="username"></param>
        /// <returns></returns>
        public async Task<List<Project>> QueryProjectsByUserName(string username)
        {
            return await projectDal.QueryProjectsByUserName(username);
        }

        /// <summary>
        /// 判断是否存在名字重复的项目
        /// </summary>
        /// <param name="projectName"></param>
        /// <returns></returns>
        public async Task<bool> isProjectNameRepated(string projectName)
        {
            return await projectDal.isProjectNameRepated(projectName);
        }

        /// <summary>
        /// 修改项目的落地机构和合作方的个数、分成金额、或者学校管理费比例时，更新项目（和流水）相关的金额数据
        /// </summary>
        /// <param name="projectToBeUpdated"></param>
        /// <param name="incomeStreams"></param>
        /// <returns></returns>
        public async Task<List<IncomeStream>> DealWithChangedAmountOfProject(Project projectToBeUpdated, List<IncomeStream> incomeStreams)
        {

            // 解析项目的落地机构和合作方json字符串
            // todo client
            List<LandingAgency> clients = JsonConvert.DeserializeObject<List<LandingAgency>>(projectToBeUpdated.clients);
            List<LandingAgency> landingAgencies = JsonConvert.DeserializeObject<List<LandingAgency>>(projectToBeUpdated.landingAgencies);
            List<Partner> partners = JsonConvert.DeserializeObject<List<Partner>>(projectToBeUpdated.partners);

            // 重置项目的所有落地机构和技术方的分成金额、以及学校管理费等
            // todo client
            clients.ForEach(client => client.shareAmount = 0);
            landingAgencies.ForEach(agency => agency.shareAmount = 0);
            partners.ForEach(partners => partners.shareAmount = 0);
            projectToBeUpdated.schoolManageAmount = 0;
            projectToBeUpdated.devFundingAmount = 0;
            projectToBeUpdated.classPayAmount = 0;
            projectToBeUpdated.welfareAmount = 0;

            // 更新项目的学校管理费等
            decimal paidAmount = projectToBeUpdated.paidAmount;

            List<LandingAgency> tmp3 = JsonConvert.DeserializeObject<List<LandingAgency>>(JsonConvert.SerializeObject(clients));
            List<LandingAgency> tmp1 = JsonConvert.DeserializeObject<List<LandingAgency>>(JsonConvert.SerializeObject(landingAgencies));
            List<Partner> tmp2 = JsonConvert.DeserializeObject<List<Partner>>(JsonConvert.SerializeObject(partners));
            // 遍历收入流水，重新计算收入流水的每种分成比例，学校管理费等。。
            // 需要注意落地机构或者合作方个数发生变化的情况
            incomeStreams.ForEach(incomeStream =>
            {
                // 这里把项目的落地机构和技术合作方复制给项目所属的收入流水(deep copy)
                // TODO CLIENT
                List<LandingAgency> incomeStreamClients = tmp3;
                List<LandingAgency> incomeStreamLandingAgencies = tmp1;
                List<Partner> incomeStreamPartners = tmp2;


                decimal income = incomeStream.incomeAmount;

                // 该条收入流水所有落地机构的分成
                decimal incomeStreamLandingAgencyAmounts = 0;
                // 更新收入流水的落地机构
                for (int i = 0; i < incomeStreamLandingAgencies.Count; i++)
                {
                    // --------------------0.01-------------------
                    incomeStreamLandingAgencies[i].shareAmount = incomeStreamLandingAgencies[i].shareRadio * income * 0.01M;
                    // 把该落地机构分成汇总到项目对应的落地机构分成中
                    landingAgencies[i].shareAmount += incomeStreamLandingAgencies[i].shareAmount;
                    // 累加该条流水所有落地机构的分成
                    incomeStreamLandingAgencyAmounts += incomeStreamLandingAgencies[i].shareAmount;
                }

                // todo client
                // 该条收入流水所有委托方的分成
                decimal incomeStreamClientsAmounts = 0;
                // 更新收入流水的委托方
                for (int i = 0; i < incomeStreamClients.Count; i++)
                {
                    // --------------------0.01-------------------
                    incomeStreamClients[i].shareAmount = incomeStreamClients[i].shareRadio * income * 0.01M;
                    // 把委托方分成汇总到项目对应的委托方分成中
                    clients[i].shareAmount += incomeStreamClients[i].shareAmount;
                    // 累加该条流水所有委托方的分成
                    incomeStreamClientsAmounts += incomeStreamClients[i].shareAmount;
                }

                // 该条收入流水所有技术合作方的分成
                decimal incomeStreamPartnerAmounts = 0;
                // 更新收入流水的合作方
                for (int i = 0; i < incomeStreamPartners.Count; i++)
                {
                    decimal bias = 0;
                    // 如果按公式来就需要减去该项目所有落地机构分成、还有面授费用。
                    if (incomeStreamPartners[i].caculation == "公式")
                    {
                        // 前面重新计算落地机构分成的过程中已经将分成汇总到培训项目的落地机构分成金额中（landingAgencies[i].shareAmount）
                        bias = incomeStreamLandingAgencyAmounts + incomeStream.payM + incomeStream.payN + incomeStream.payP;
                    }
                    // --------------------0.01-------------------
                    incomeStreamPartners[i].shareAmount = (income - bias) * incomeStreamPartners[i].shareRadio * 0.01M;
                    // 累加该条流水所有技术合作方的分成
                    incomeStreamPartnerAmounts += incomeStreamPartners[i].shareAmount;
                    // 把该技术合作方分成汇总到项目
                    partners[i].shareAmount += incomeStreamPartners[i].shareAmount;
                }

                // 如果是非区域项目，为入账-委托方分成-落地机构分成-技术方分成
                // todo client
                decimal agencyPartnerAmounts = projectToBeUpdated.categories != "非区域项目" ? 0 : (incomeStreamLandingAgencyAmounts + incomeStreamPartnerAmounts + incomeStreamClientsAmounts);
                // realAmounts * radio = 学校管理费等等的分成
                decimal realAmounts = income - agencyPartnerAmounts;

                // --------------------0.01-------------------
                // 更新流水的学校管理费等
                incomeStream.schoolManageAmount = realAmounts * projectToBeUpdated.schoolManageRadio * 0.01M;
                incomeStream.devFundingAmount = realAmounts * projectToBeUpdated.devFundingRadio * 0.01M;
                incomeStream.welfareAmount = realAmounts * projectToBeUpdated.welfareRadio * 0.01M;
                incomeStream.classPayAmount = realAmounts * projectToBeUpdated.classPayRadio * 0.01M;
                // 更新收入流水的这四项到项目
                projectToBeUpdated.schoolManageAmount += incomeStream.schoolManageAmount;
                projectToBeUpdated.devFundingAmount += incomeStream.devFundingAmount;
                projectToBeUpdated.welfareAmount += incomeStream.welfareAmount;
                projectToBeUpdated.classPayAmount += incomeStream.classPayAmount;

                // 序列化流水的落地机构合作方等
                // todo client
                incomeStream.clients = JsonConvert.SerializeObject(incomeStreamClients);
                incomeStream.landingAgencies = JsonConvert.SerializeObject(incomeStreamLandingAgencies);
                incomeStream.partners = JsonConvert.SerializeObject(incomeStreamPartners);

            });

            // 序列化项目的落地机构合作方等，
            // todo client
            projectToBeUpdated.landingAgencies = JsonConvert.SerializeObject(landingAgencies);
            projectToBeUpdated.partners = JsonConvert.SerializeObject(partners);

            // 更新未到账金额
            projectToBeUpdated.unpaidAmount = projectToBeUpdated.projectFund - projectToBeUpdated.paidAmount;

            // 更新项目
            await projectDal.Update(projectToBeUpdated);

            // 返回待更新的某项目的所有流水
            return incomeStreams;
        }

    }
}
